#include "main.h"
#include "stdlib.h"
#include "./flash/flash_eeprom.h"
#include "./flash/stm32g0xx_ll_flash.h"

extern uint32_t Fml_Constant;; //
extern uint8_t *C;
extern uint8_t D[12];
extern uint32_t Address;
//union FLASH_BUF_TypeDef Decode;
extern uint8_t Result[4];

void Formula_12(uint8_t *D, uint8_t *Result);
extern volatile uint32_t Device_Serial[3];
extern union
{
    uint32_t ID_WORD[3];
    uint8_t ID_Byte[12];
} psswd;

union
{
    uint32_t WORD;
    uint8_t Byte[12];
} Decode;


uint8_t Encipherment(void)
{
	uint32_t err;
    uint16_t srand_data;
	FLASH_EraseInitTypeDef pEraseInit;
    psswd.ID_WORD[0] = *(__IO uint32_t*)(0x1FFF7590);
    psswd.ID_WORD[1] = *(__IO uint32_t*)(0x1FFF7590 + 4);
    psswd.ID_WORD[2] = *(__IO uint32_t*)(0x1FFF7590 + 8);

    D[0] = psswd.ID_Byte[3];
    D[1] = psswd.ID_Byte[0];
    D[2] = psswd.ID_Byte[1];
    D[3] = psswd.ID_Byte[2];
    D[4] = psswd.ID_Byte[6];
    D[5] = psswd.ID_Byte[4];
    D[6] = psswd.ID_Byte[7];
    D[7] = psswd.ID_Byte[5];
    D[8] = psswd.ID_Byte[11];
    D[9] = psswd.ID_Byte[8];
    D[10] = psswd.ID_Byte[10];
    D[11] = psswd.ID_Byte[9];
    Decode.Byte[0] = C[0] + D[0] - D[4] + D[8];
    Decode.Byte[1] = ((C[1] & D[1]) ^ D[5]) | D[9];
    Decode.Byte[2] = C[2] | (D[2] ^ D[6] ^ D[10]);
    Decode.Byte[3] = C[3] - D[3] + D[7] & D[11];
    srand_data = (Decode.Byte[0] << 8) + Decode.Byte[2] + (Decode.Byte[3] << 8) + Decode.Byte[1];
    srand(srand_data);

    __disable_irq();
    LL_Flash_Unlock();
	pEraseInit.Banks = FLASH_BANK_1;
	pEraseInit.NbPages = 1;
	pEraseInit.Page = (APP_DECODE_START_ADDR - FLASH_BASE)/FLASH_PAGE_SIZE;
	pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
	LL_FLASHEx_Erase(&pEraseInit,&err);
//    EraseSector(APP_DECODE_START_ADDR);
    uint64_t Tmp;

    for(uint16_t i = 0 ; i < 2048 / 8 ; i++)
    {
        if( i * 8 + APP_DECODE_START_ADDR == APP_DECODE_ADDR)
        {
            Tmp =  (Decode.Byte[0] << 0) | (Decode.Byte[1] << 8) | (Decode.Byte[2] << 16) | (Decode.Byte[3] << 24) | ((uint64_t)rand() << 32);
        }
        else
        {
            Tmp = rand() | ((uint64_t)rand() << 32);
        }
		LL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,APP_DECODE_START_ADDR + i * 8,Tmp);
        //ProgramPage(APP_DECODE_START_ADDR + i * 8, 8, (uint8_t *)&Tmp);
    }

    LL_Flash_lock();
    __enable_irq();
    Decode.WORD =   *(__IO uint32_t*)APP_DECODE_ADDR;
    Get_UID();

    if(Decode.Byte[0] != Result[0] || Decode.Byte[1] != Result[1] ||
            Decode.Byte[2] != Result[2] || Decode.Byte[3] != Result[3])
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
void Formula_12(uint8_t *D, uint8_t *Result)
{
    Result[0] = C[0] + D[0] - D[4] + D[8];
    Result[1] = ((C[1] & D[1]) ^ D[5]) | D[9];
    Result[2] = C[2] | (D[2] ^ D[6] ^ D[10]);
    Result[3] = C[3] - D[3] + D[7] & D[11];
}
